#include "STPReader.h"

STEPControl_Reader STPReader::ReadSTP(const std::string& path)
{
	// 创建读取器
	STEPControl_Reader reader;
	reader.ReadFile(Standard_CString(path.c_str()));

	// 检查读取信息
	reader.PrintCheckLoad(Standard_True, IFSelect_ItemsByEntity);

	// 获得可翻译的根实体数量，然后翻译所有实体，获得成功的数量
	Standard_Integer NbRoots = reader.NbRootsForTransfer();
	Standard_Integer NbTrans = reader.TransferRoots();

	// 检查翻译信息
	reader.PrintCheckTransfer(Standard_True, IFSelect_ItemsByEntity);

	return reader;
}

TColGeom_SequenceOfCurve STPReader::ReadCurve(STEPControl_Reader& reader)
{
	TColGeom_SequenceOfCurve curves;
	for (int i = 1; i <= reader.NbShapes(); i++)
	{
		auto& shape = reader.Shape(i);
		TopExp_Explorer Ex;
		for (Ex.Init(shape, TopAbs_EDGE); Ex.More(); Ex.Next())
		{
			TopoDS_Edge E;
			E = TopoDS::Edge(Ex.Current());

			BRep_Tool tool;
			Standard_Real first, second;
			Handle(Geom_Curve) curve = tool.Curve(E, first, second);
			curves.Append(curve);
		}
	}
	return curves;
}

TColGeom_SequenceOfSurface STPReader::ReadSurface(STEPControl_Reader& reader)
{
	TColGeom_SequenceOfSurface surfaces;
	for (int i = 1; i <= reader.NbShapes(); i++)
	{
		auto& shape = reader.Shape(i);
		TopExp_Explorer Ex;
		for (Ex.Init(shape, TopAbs_FACE); Ex.More(); Ex.Next())
		{
			TopoDS_Face F;
			F = TopoDS::Face(Ex.Current());

			BRep_Tool tool;
			TopLoc_Location L;
			Handle(Geom_Surface) surface = tool.Surface(F, L);
			surfaces.Append(surface);
		}
	}
	return surfaces;
}

GLCurvePtr STPReader::AsGLCurve(Handle(Geom_Curve) curve)
{
	std::vector<glm::vec3> vertices;
	const int N = 1000;
	double first = curve->FirstParameter();
	double last = curve->LastParameter();
	double step = (last - first) / (N - 1);
	for (int i = 0; i < N; i++)
	{
		gp_Pnt P;
		curve->D0(first + i * step, P);
		vertices.push_back({ P.X(), P.Y(), P.Z() });
	}

	return GLCurvePtr(new GLCurve(vertices));
}

GLCurvePtr STPReader::AsGLCurve(Handle(Geom2d_Curve) curve)
{
	std::vector<glm::vec3> vertices;
	const int N = 1000;
	double first = curve->FirstParameter();
	double last = curve->LastParameter();
	double step = (last - first) / (N - 1);
	for (int i = 0; i < N; i++)
	{
		gp_Pnt2d P;
		curve->D0(first + i * step, P);
		vertices.push_back({ P.X(), 0, P.Y() });
	}

	return GLCurvePtr(new GLCurve(vertices));
}

GLMeshPtr STPReader::AsGLMesh(Handle(Geom_Surface) surf)
{
	Handle(Geom_BSplineSurface) surface = Handle(Geom_BSplineSurface)::DownCast(surf);

	double bu, eu, bv, ev;
	surface->Bounds(bu, eu, bv, ev);
	std::vector<GLVertex> vertices(100 * 100);
	std::vector<unsigned int> indices(99 * 99 * 6);

	for (int i = 0; i < 100; i++)
	{
		for (int j = 0; j < 100; j++)
		{
			int k = i * 100 + j;

			float u = bu + (eu - bu) / 99 * i;
			float v = bv + (ev - bv) / 99 * j;
			
			gp_Pnt P;
			gp_Vec Pu, Pv;
			surface->D1(u, v, P, Pu, Pv);
			gp_Vec n = Pu.Crossed(Pv).Normalized();

			GLVertex& vertex = vertices[i * 100 + j];
			vertex.position = { P.X(), P.Y(), P.Z() };
			vertex.normal = { n.X(), n.Y(), n.Z() };
			vertex.texCoords = { i / 99.0, j / 99.0 };
		}
	}

	for (int i = 0; i < 99; i++)
	{
		for (int j = 0; j < 99; j++)
		{
			// 四边形分割成两个三角形
			int k = i * 99 + j;
			indices[k * 6 + 0] = i * 100 + j;
			indices[k * 6 + 1] = i * 100 + j + 1;
			indices[k * 6 + 2] = (i + 1) * 100 + j;
			indices[k * 6 + 3] = i * 100 + j + 1;
			indices[k * 6 + 4] = (i + 1) * 100 + j + 1;
			indices[k * 6 + 5] = (i + 1) * 100 + j;
		}
	}

	return GLMeshPtr(new GLMesh(vertices, indices));
}

GLMeshPtr STPReader::AsParaGLMesh(Handle(Geom_Surface) surf)
{
	Handle(Geom_BSplineSurface) surface = Handle(Geom_BSplineSurface)::DownCast(surf);

	double bu, eu, bv, ev;
	surface->Bounds(bu, eu, bv, ev);
	std::vector<GLVertex> vertices(100 * 100);
	std::vector<unsigned int> indices(99 * 99 * 6);

	for (int i = 0; i < 100; i++)
	{
		for (int j = 0; j < 100; j++)
		{
			int k = i * 100 + j;

			float u = bu + (eu - bu) / 99 * i;
			float v = bv + (ev - bv) / 99 * j;

			GLVertex& vertex = vertices[i * 100 + j];
			vertex.position = { u, 0, v };
			vertex.normal = { 0, 1, 0 };
			vertex.texCoords = { i / 99.0, j / 99.0 };
		}
	}

	for (int i = 0; i < 99; i++)
	{
		for (int j = 0; j < 99; j++)
		{
			// 四边形分割成两个三角形
			int k = i * 99 + j;
			indices[k * 6 + 0] = i * 100 + j;
			indices[k * 6 + 1] = i * 100 + j + 1;
			indices[k * 6 + 2] = (i + 1) * 100 + j;
			indices[k * 6 + 3] = i * 100 + j + 1;
			indices[k * 6 + 4] = (i + 1) * 100 + j + 1;
			indices[k * 6 + 5] = (i + 1) * 100 + j;
		}
	}

	return GLMeshPtr(new GLMesh(vertices, indices));
}
